#include "MouseState.h"

#include <cstring>
#include <SDL_events.h>

MouseState::MouseState()
    : mX(0)
    , mY(0)
{
    memset(mMouseButtonState, 
        static_cast<uint8_t> (mouseButtonState::NOT_PRESSED),
        3 * sizeof(mouseButtonState));

    memset(mMouseButtonEventState, 
        static_cast<uint8_t> (mouseButtonEventState::NO_EVENT),
        3 * sizeof(mouseButtonEventState));
}

void MouseState::init() {
    // Updates mouse position and mouse buttons state
    const uint32_t state = SDL_GetMouseState(&mX, &mY);
    mMouseButtonState[0] = 
        (state & SDL_BUTTON(1)) ? mouseButtonState::PRESSED
        : mouseButtonState::NOT_PRESSED;

    mMouseButtonState[1] = 
        (state & SDL_BUTTON(2)) ? mouseButtonState::PRESSED
        : mouseButtonState::NOT_PRESSED;

    mMouseButtonState[2] = 
        (state & SDL_BUTTON(3)) ? mouseButtonState::PRESSED
        : mouseButtonState::NOT_PRESSED;

    // No mouse buttons events at initialization
    memset(mMouseButtonEventState, 
        static_cast<uint8_t> (mouseButtonEventState::NO_EVENT),
        3 * sizeof(mouseButtonEventState));

}

void MouseState::updateButtonsState() {
    const uint32_t state = SDL_GetMouseState(nullptr, nullptr);
    mMouseButtonState[0] = 
        (state & SDL_BUTTON(1)) ? mouseButtonState::PRESSED
        : mouseButtonState::NOT_PRESSED;

    mMouseButtonState[1] = 
        (state & SDL_BUTTON(2)) ? mouseButtonState::PRESSED
        : mouseButtonState::NOT_PRESSED;

    mMouseButtonState[2] = 
        (state & SDL_BUTTON(3)) ? mouseButtonState::PRESSED
        : mouseButtonState::NOT_PRESSED;
}

void MouseState::clearMouseEvents() {
    memset(mMouseButtonEventState, 
        static_cast<uint8_t> (mouseButtonEventState::NO_EVENT),
        3 * sizeof(mouseButtonEventState));
}

void MouseState::handleMouseButtonEvent(const SDL_MouseButtonEvent& event) {
    const mouseButtonEventState state = 
        (event.type == SDL_MOUSEBUTTONDOWN) ? mouseButtonEventState::PRESSED
        : mouseButtonEventState::RELEASED;

    const uint8_t buttonIndex = 
        (event.button == SDL_BUTTON_LEFT) ? 0 
        : (event.button == SDL_BUTTON_MIDDLE) ? 1
        : 2;
    mMouseButtonEventState[buttonIndex] = state;
}

void MouseState::handleMouseMotionEvent(const SDL_MouseMotionEvent& event) {
    mX = event.x;
    mY = event.y;
}